package com.sf.osms.dep.quartz;

import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.sf.novatar.cluster.IKeepAliveAndLockResolver;
import com.sf.osms.dep.biz.ICommonServiceBiz;
import com.sf.osms.dep.domain.ChargeBase;
import com.sf.osms.dep.domain.Router;
import com.sf.osms.dep.processor.util.CollectionUtil;
import com.sf.osms.dep.processor.util.DateUtil;
import com.sf.osms.dep.processor.util.ExceptionUtils;
import com.sf.osms.dep.processor.util.RouterConstants;
import com.sf.osms.dep.processor.util.SwitchUtils;
import com.sf.osms.dep.processor.util.WebserviceUtil;
import com.sf.osms.dep.webservice.bsp.AckbillDto;
import com.sf.osms.dep.webservice.bsp.AckbillServiceDto;
import com.sf.osms.dep.webservice.wqs.BillInfo;
import com.sf.osms.dep.webservice.wqs.Header;
import com.sf.osms.dep.webservice.wqs.Sbody;
import com.sf.osms.dep.webservice.wqs.Shead;
import com.sf.osms.dep.webservice.wqs.WaybillAll;
import com.sf.osms.dep.webservice.wqs.WaybillFee;
import com.sf.osms.dep.webservice.wqs.WaybillServiceInfo;

public class PodSignJob{
	private static Logger logger = LoggerFactory.getLogger(PodSignJob.class);
	private static final ExecutorService threadService = Executors.newFixedThreadPool(30);
	private static final Random random = new Random();
	
	@Autowired
	private  IKeepAliveAndLockResolver clusterSync;
	
	@Autowired
	private ICommonServiceBiz commonRouteService;
	private static String POD_SYNC_PREFIXX = "dep_pod_lock_";

	protected void job(){

		logger.info("*****定时任务开始执行（"+DateUtil.dateFomat(new Date(), "yyyy-MM-dd HH:mm:ss")+"）*****");	
		Set<String> agentCuntries = commonRouteService.queryAgentCountry();
		Iterator<String> iterator = agentCuntries.iterator();
		while(iterator.hasNext()){
			String country = iterator.next();
			
			//每个代理一个线程进行处理
			threadService.execute(new Runnable() {
				
				@Override
				public void run() {
							
						try {
							Thread.sleep(random.nextInt(3000));
						} catch (InterruptedException e) {
							logger.error(ExceptionUtils.getExceptionStackString(e));
						}
						
						try {
							if(clusterSync.isLockedFor(POD_SYNC_PREFIXX + country)){
								return;
							}
							
							boolean lock = clusterSync.getLockFor(POD_SYNC_PREFIXX + country);
							if(!lock){
								return;
							} 
							logger.info("******开始处理dep进行回单推送******");
							if(SwitchUtils.getSwithBySystemName(SwitchUtils.BSP_SWITCH_NAME)){
								handlPodRouter(country);
							}
							logger.info("******完成dep的回单推送******");
						} catch (Exception e) {
							logger.error(ExceptionUtils.getExceptionStackString(e));
							logger.error("****dep推送异常******");
						}finally{
							clusterSync.releaseLockFor(POD_SYNC_PREFIXX + country);
						}
					
				}
			});
			
		}
		
		
	}
	
	
	public void handlPodRouter(String country){
		 	List<Router> queryRouterNeedPod = commonRouteService.queryRouterNeedPod(country);
		 	
		 	if(CollectionUtil.isEmpty(queryRouterNeedPod)){
		 		return;
		 	}
		 	Map<String,Router> routerMap = new HashMap<String,Router>();
		 
		 
		 	for (Router router : queryRouterNeedPod) {
		 		router.setPodStatus(11); //wqs没有运单的信息
		 		router.setPodSendCount(router.getSendCount() == null ? 1 : router.getSendCount()+1);
				if(router.getPodSendCount() >= 5){
					router.setPodStatus(20); //回单调用大于五次的路由记录状态
				}
				router.setStatusDt(new Date()); //更新调用时间
				routerMap.put(router.getSfWaybill(), router);
			}
		 	
			Map<String,ChargeBase> handOver = commonRouteService.queryHandOverInfo(routerMap.keySet());
			
			Header header = new Header();
			Shead sHead = new Shead();
			sHead.setSYSTEMID(RouterConstants.DEP_TO_WQS_NAME);
			sHead.setUSERLANG(RouterConstants.DEP_TO_WQS_LANGUAGE);
			sHead.setCOUNTRY(country);
			Sbody sBody = new Sbody();
			sBody.setWaybillNo(new ArrayList<String>(routerMap.keySet())); //运单号集合
			sBody.setDataType(RouterConstants.DEP_TO_WQS_DATA_TYPE);
			sBody.setInputTypeCode(RouterConstants.DEP_IN_WQS_DATA_CODE);
			List<WaybillAll> waybillAll = null;
			try {
				waybillAll = WebserviceUtil.invokeWQS(header, sHead, sBody);
			} catch (Exception e) {
				logger.error("*****dep回单调用WQS接口异常******");
				logger.error(ExceptionUtils.getExceptionStackString(e));
				//进行状态的重置
				for (Router router : queryRouterNeedPod) {
					router.setPodStatus(0); 
					router.setPodBspRetInfo("调用wqs接口异常");
				}
			}
			
			
			if(!CollectionUtil.isEmpty(waybillAll)){
				for (WaybillAll wayBillInfo : waybillAll) {
					String wayBillNoNew = wayBillInfo.getWaybillNo();
					Router router = routerMap.get(wayBillNoNew);
					if(null == router){
						List<String> childNos = wayBillInfo.getChildNos();
						if(!CollectionUtil.isEmpty(childNos)){
							for (String childNo : childNos) {
								Router routerChild = routerMap.get(childNo);
								if(routerChild != null){
									routerChild.setPodStatus(12); //该运单为子运单
									break;
								}
							}
						}
						
					}else{
						//进行清单和路由组装为BSP所需的对象
						AckbillDto assembleAckbillDto = assembleAckbillDto(handOver,wayBillInfo,router);
						String bspReturnStatus = null;
						try {
							bspReturnStatus = WebserviceUtil.invokeBSP(assembleAckbillDto);
						} catch (Exception e) {
							logger.error("*****dep回单调用BSP接口异常******");
							logger.error(ExceptionUtils.getExceptionStackString(e));
							//进行状态的重置
							router.setPodBspRetInfo("调用bsp接口异常");
							router.setPodStatus(0); 
						}
						
						//进行router对象状态的回填
						handleRouterStatus(router,bspReturnStatus);
						
					}
					
				}
			}
			
			//批量更新路由状态
			
			commonRouteService.updateRoute(queryRouterNeedPod);
			
			
	}
	
	private void handleRouterStatus(Router router, String bspReturnStatus) {
		if(StringUtils.isEmpty(bspReturnStatus)){
			return ;
		}
		router.setPodBspRetInfo(bspReturnStatus);
		if(bspReturnStatus.equalsIgnoreCase("success")){
			router.setPodStatus(1); //进行bsp success状态的重置
		}else{
			router.setPodStatus(13);  //其他的bsp 状态
		}
		
	}

	
	/**
	 * 装配BSP接口对象
	 * @param handOver
	 * @param waybillAll
	 * @param router
	 * @return
	 */
	public AckbillDto assembleAckbillDto(Map<String,ChargeBase> handOver,WaybillAll waybillAll,Router router){
		
		ChargeBase hand = handOver.get(router.getSfWaybill());
		
		AckbillDto dto = new AckbillDto();
		dto.setAckbillTypeCode("1");
		dto.setInputSystem("dep");
		dto.setInputerEmpCode("system");
		dto.setOneselfPickupFlg(2L);
		dto.setMeterageWeightQty(0.0);
		dto.setWaybillRemark("");
		dto.setFreeTicketNo("");
		dto.setUnifiedCode("");
		
		dto.setDestZoneCode(router.getNetNum()); //节点的网点代码
		dto.setWaybillNo(router.getSfWaybill());  //运单号
		dto.setDeliverEmpCode(router.getOperatorId()); //操作员
		dto.setSubscriberName(router.getPhoneZone()); //回签内容
		if(StringUtils.isNotBlank(dto.getSubscriberName()) && dto.getSubscriberName().length() > 20){
			dto.setSubscriberName(dto.getSubscriberName().substring(0, 20));
		}
		try {
			dto.setSigninTm(tranferDateAndTime(router.getBarDate(), router.getBarTime())); //把枪时间
		} catch (Exception e) {
		}
		BillInfo sendBill = waybillAll.getSendBill();
		if( sendBill != null){
			dto.setOneselfPickupFlg(sendBill.getOneselfPickupFlg() == 1L ? 1L:2L);
			dto.setMeterageWeightQty(sendBill.getMeterageWeightQty());
			dto.setWaybillRemark(sendBill.getWaybillRemk());
			dto.setUnifiedCode(sendBill.getUnifiedCode());
		}
		
		//费用信息处理
		List<WaybillFee> sendFees = waybillAll.getSendFee();
		handleWaybillFee(sendFees,dto,hand,router);
		
		//增值服务费用处理
		List<AckbillServiceDto> handleServiceProd = handleServiceProd(waybillAll);
		if(!CollectionUtil.isEmpty(handleServiceProd)){
			dto.setServiceList(handleServiceProd);
		}
		
		return dto;
	}
	
	
	public WaybillFee findWaybillFeeByFeeTypeCode(WaybillAll waybillAll,String feeTypeCode){
		List<WaybillFee> sendFees = waybillAll.getSendFee();
	
		for(int i=0;i<sendFees.size();i++){
			WaybillFee sendFee = sendFees.get(i);
			if(feeTypeCode.equals(sendFee.getFeeTypeCode())) {
				return sendFee;
			}
		}
		return null;
	}
	
	
	/**
	 * 时间格式的处理
	 * @param oldBarDate
	 * @param oldBarTime
	 * @return
	 * @throws Exception
	 */
	public XMLGregorianCalendar tranferDateAndTime(Date oldBarDate,Date oldBarTime) throws Exception{

		String date = DateUtil.dateFomat(oldBarDate, "yyyy-MM-dd");
		String time = DateUtil.dateFomat(oldBarTime, "HH:mm:ss");
		Date parseDate = DateUtils.parseDate(date + time, new String[] {
				"yyyy-MM-ddHH:mm:ss"
		});
		GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(parseDate);
        XMLGregorianCalendar gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
  
        return gc;
	}
	
	/**
	 * 处理附加服务费
	 * @param waybillAll
	 * @return
	 */
	public List<AckbillServiceDto> handleServiceProd(WaybillAll waybillAll){
		List<AckbillServiceDto> asd = new ArrayList<AckbillServiceDto>();
		List<WaybillServiceInfo> sendServices = waybillAll.getSendService();
		if(!CollectionUtil.isEmpty(sendServices)){
			for (WaybillServiceInfo sendService : sendServices) {
				String serviceProdCode = sendService.getServiceProdCode();
				if("IN66".equals(serviceProdCode)){
					continue;
				}
				
				AckbillServiceDto waybillService = new AckbillServiceDto();
				waybillService.setServiceProdCode(sendService.getServiceProdCode());
				
				if("IN01".equals(serviceProdCode)){
					WaybillFee wayBillFee = findWaybillFeeByFeeTypeCode(waybillAll,"5");
					waybillService.setAttribute1(wayBillFee.getFeeAmt().toString());
					
				}else if("IN02".equals(serviceProdCode)){
					WaybillFee wayBillFee = findWaybillFeeByFeeTypeCode(waybillAll,"3");
					waybillService.setAttribute1(wayBillFee.getFeeAmt().toString());
					waybillService.setAttribute2(sendService.getAttribute1());
					
				}else if("IN05".equals(serviceProdCode)){
					
					//FIXME:
					if("0".equals(sendService.getAttribute1()) || StringUtils.isEmpty(sendService.getAttribute1())){
						continue;
					}
					waybillService.setAttribute1(sendService.getAttribute1());
					
				}else if("IN15".equals(serviceProdCode)){
				
					WaybillFee wayBillFee = findWaybillFeeByFeeTypeCode(waybillAll,"14");
					waybillService.setAttribute1(wayBillFee.getFeeAmt().toString());
				}else if("IN18".equals(serviceProdCode)){
					
					//FIXME;
					if(StringUtils.isEmpty(sendService.getAttribute2()) || sendService.getAttribute2().trim().equals("0")){
						continue;
					}
					waybillService.setAttribute1(sendService.getAttribute1());
					waybillService.setAttribute2(sendService.getAttribute2());
				}else if("OS01".equals(serviceProdCode)){
					
					WaybillFee wayBillFee = findWaybillFeeByFeeTypeCode(waybillAll,"14");
					waybillService.setAttribute1(wayBillFee.getFeeAmt().toString());
				}else {
					
					waybillService.setAttribute1(sendService.getAttribute1());
					waybillService.setAttribute2(sendService.getAttribute2());
				}
				
				asd.add(waybillService);
			}
		}
		return asd;
	}
	
	/**
	 * 处理清单中费用项，向AckbillDto填充值
	 * @param sendFees
	 * @param dto
	 */
	public void handleWaybillFee(List<WaybillFee> sendFees,AckbillDto dto,ChargeBase hand,Router router){
		if(!CollectionUtil.isEmpty(sendFees)){
			for (WaybillFee sendFee : sendFees) {
				if(!"1".equals(sendFee.getFeeTypeCode())){
					continue;
				}
				
				if("1".equals(sendFee.getPaymentTypeCode())){
					dto.setPaymentTypeCode(sendFee.getPaymentTypeCode());
					dto.setGatherZoneCode(sendFee.getGatherZoneCode());
					break;
				}else if("2".equals(sendFee.getPaymentTypeCode()) && ((hand == null) || (!"2".equals(hand.getPaymentType()) && !"3".equals(hand.getPaymentType()) ))){
					dto.setGatherZoneCode(router.getNetNum());
					dto.setPaymentTypeCode(sendFee.getPaymentTypeCode());
					break;
				}else if("3".equals(sendFee.getPaymentTypeCode()) && ((hand == null) || (!"2".equals(hand.getPaymentType()) && !"3".equals(hand.getPaymentType()) ))){
					dto.setPaymentChangeTypeCode("1");
					dto.setCodBillFlg(2L);
					dto.setTransferParcelFlg(2L);
					dto.setPaymentTypeCode(sendFee.getPaymentTypeCode());
					dto.setCustomerAcctCode(sendFee.getCustomerAcctCode());
					dto.setGatherZoneCode(sendFee.getGatherZoneCode());
					break;
				}else if("2".equals(sendFee.getPaymentTypeCode()) && (null != hand && "2".equals(hand.getPaymentType()))){
					dto.setPaymentTypeCode("2");
					dto.setGatherZoneCode(router.getNetNum());
					if(StringUtils.isNotEmpty(hand.getCreditAccount())){
						dto.setCustomerAcctCode(hand.getCreditAccount());
					}else{
						dto.setAddresserAddrNative(null);
					}
					break;
				}else if("2".equals(sendFee.getPaymentTypeCode()) && (null != hand && "3".equals(hand.getPaymentType()))){
					dto.setPaymentChangeTypeCode("2");
					dto.setPaymentTypeCode("3");
					dto.setCodBillFlg(2L);
					dto.setTransferParcelFlg(2L);
					
					if(StringUtils.isNotEmpty(hand.getNetwork())){
						dto.setGatherZoneCode(hand.getNetwork());
					}else{
						//FIXME:确认
						dto.setGatherZoneCode(router.getNetNum());
					}
					
					if(StringUtils.isNotEmpty(hand.getCreditAccount())){
						dto.setCustomerAcctCode(hand.getCreditAccount());
					}
					break;
				}else if("3".equals(sendFee.getPaymentTypeCode()) && (null != hand && "2".equals(hand.getPaymentType()))){
					dto.setPaymentChangeTypeCode("2");
					dto.setGatherZoneCode(hand.getNetwork());
					if(StringUtils.isEmpty(hand.getCreditAccount())){
						dto.setPaymentTypeCode("3");
					}else{
						dto.setPaymentTypeCode("2");
					}
					
					dto.setCustomerAcctCode(hand.getCreditAccount());
					break;
				}else if("3".equals(sendFee.getPaymentTypeCode()) && (null != hand && "3".equals(hand.getPaymentType()))){
					dto.setPaymentChangeTypeCode("2");
					dto.setCodBillFlg(2L);
					dto.setTransferParcelFlg(2L);
					dto.setPaymentTypeCode(sendFee.getPaymentTypeCode());
					dto.setCustomerAcctCode(sendFee.getCustomerAcctCode());
					dto.setGatherZoneCode(sendFee.getGatherZoneCode());
					
					break;
				}
			}
		}
	}
}
